﻿using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Browser;
using System.Collections.Generic;
using System.Windows.Threading;


namespace Microsoft.ProductivityHub.SilverlightProductCarousel
{
	public partial class VideoCarousel : UserControl
	{
        public List<CarouselItem> CarouselList;
        Double Center = 0;
        Double ItemWidth = 220;
        Double DefaultTop = 5;
        DispatcherTimer SlideTimer = new DispatcherTimer();

        // --------------------------------------------------------------------------------------
        // INITIALIZE COMPONENT
        // --------------------------------------------------------------------------------------
        
		public VideoCarousel()
		{
			// Required to initialize variables
			InitializeComponent();

            SlideTimer.Interval = new TimeSpan(0, 0, 0, 0, 40); // Days, Hours, Minutes, Seconds, Milliseconds
            SlideTimer.Tick += new EventHandler(SlideTimer_Tick);

            LayoutRoot.MouseWheel += new MouseWheelEventHandler(LayoutRoot_MouseWheel);
		}

        void LayoutRoot_MouseWheel(object sender, MouseWheelEventArgs e)
        {
            if (e.Delta < 0)
            {
                StepRight();
                e.Handled = true;
            }
            else if (e.Delta > 0)
            {
                StepLeft();
                e.Handled = true;
            }
        }




        // --------------------------------------------------------------------------------------
        // CAROUSEL CONSTRUCTOR
        // --------------------------------------------------------------------------------------
        //
        // This section contains functions that build out the carousel content

        public void CreateList(int Count)
        {
            CarouselList = new List<CarouselItem>(Count);
        }

        public void StartCarousel()
        {
            if (CarouselList.Count > 0)
            {
                MySlider.Maximum = CarouselList.Count - 1;
                FindCenter();
                InitializeItems();
                DistributeItems();
                JumpToPosition();
                ShowItems();

                // add behavior to randomly select a product on Start and have it as the jumped item
                Random r = new Random();
                int randomStartIndex = r.Next(CarouselList.Count);
                GoToItem(randomStartIndex);
                ShowTitle(randomStartIndex); // show the title of the random item;
            }
        }

        public void ShowItems()
        {
            for (int i = 0; i < CarouselList.Count; i++)
            {
                CarouselList[i].ShowItem.Begin();
            }
        }

        public void InitializeItems()
        {
            for (int i = 0; i < CarouselList.Count; i++)
            {
                CarouselItem ThisItem = CarouselList[i];
                Canvas.SetTop(ThisItem, DefaultTop);
                Point CenterPoint = new Point(.5,.5);
                ThisItem.RenderTransformOrigin = CenterPoint;
                ThisItem.ShuffleToItem += new CarouselItem.ShuffleToItemEvent(GoToItem);
                ThisItem.ShowTitle += new CarouselItem.ShowTitleEvent(ShowTitle);
            }
        }

        private void ShowTitle(int index)
        {
            if (CarouselList != null && CarouselList.Count > 0)
            {
                VideoTitle.Text = CarouselList[index].Title;
                VideoTitle.Tag = CarouselList[index].Data;
            }
        }

        private void HideTitle()
        {
            // HideTitle_SB.Begin();
        }




        // --------------------------------------------------------------------------------------
        // CAROUSEL POSITION FUNCTIONS
        // --------------------------------------------------------------------------------------
        //
        // This section contains functions that set positioning of items in the carousel

        private void FindCenter()
        {
            Center = CarouselCanvas.Width / 2;
            Center = Math.Round(Center);
            Center = Center - 110;
        }


        private void DistributeItems()
        {
            for (int i = 0; i < CarouselList.Count; i++)
            {
                CarouselList[i].IsActive = false;

                if (i < MySlider.Value)
                {
                    DistributeLeft(i);
                }
                else if (i == MySlider.Value)
                {
                    DistributeCenter(i);
                    CarouselList[i].IsActive = true;
                }
                else if (i > MySlider.Value)
                {
                    DistributeRight(i);
                }
            }
        }

        // Distribute left, right, center
        private void DistributeLeft(int i)
        {
            Double Distance = MySlider.Value - i;
            Double Scale = GetScale(Distance);
            Double Position = GetPosition(Distance, true);
            Double Top = GetTop(Distance);
            Double Alpha = GetAlpha(Distance);
            int Zindex = GetZindex(Distance, i);

            SetTargetValues(i, Scale, Position, Top, Alpha, Zindex);
        }

        private void DistributeRight(int i)
        {
            Double Distance = i - MySlider.Value;
            Double Scale = GetScale(Distance);
            Double Position = GetPosition(Distance, false);
            Double Top = GetTop(Distance);
            Double Alpha = GetAlpha(Distance);
            int Zindex = GetZindex(Distance, i);

            SetTargetValues(i, Scale, Position, Top, Alpha, Zindex);
        }

        private void DistributeCenter(int i)
        {
            Double Scale = 1;
            Double Position = Center;
            Double Top = DefaultTop;
            Double Alpha = 1;
            int Zindex = 0;

            SetTargetValues(i, Scale, Position, Top, Alpha, Zindex);
        }

        // Set the target values for each item
        private void SetTargetValues(int i, Double Scale, Double Position, Double Top, Double Alpha, int Zindex)
        {
            CarouselItem ThisItem = CarouselList[i];
            ThisItem.NewScale = Scale;
            ThisItem.NewPosition = Position;
            ThisItem.NewTop = Top;
            ThisItem.NewAlpha = Alpha;
            ThisItem.NewZindex = Zindex;
            ThisItem.IsVisible = false;
            if (Alpha > 0)
            {
                ThisItem.IsVisible = true;
            }
        }

        // Set the current values for each item
        private void GetCurrentValues(int i)
        {
            CarouselItem ThisItem = CarouselList[i];
            ThisItem.Position = Canvas.GetLeft(ThisItem);
            ThisItem.Top = Canvas.GetTop(ThisItem);
            ThisItem.Zindex = Canvas.GetZIndex(ThisItem);
            ThisItem.Scale = ThisItem.ItemScale.ScaleX;
            ThisItem.Alpha = ThisItem.Content.Opacity;
        }


        // Return the values for each target value

        private Double GetScale(Double Distance)
        {
            Double Scale = 1 - (.15 * Distance);
            return Scale;
        }

        private Double GetPosition(Double Distance, Boolean IsLeft)
        {
            Double Position = ItemWidth * Distance;
            Position = Position - (Distance * 140);

            if (IsLeft == true)
            {
                Position = Center -Position;
            }
            else if (IsLeft == false)
            {
                Position = Position + Center;
            }

            Position = Math.Round(Position);
            return Position;
        }

        private Double GetTop(Double Distance)
        {
            Double Offset = Distance * 3;
            Double Top = DefaultTop - Offset;
            return Top;
        }

        private Double GetAlpha(Double Distance)
        {
            Double NewAlpha = 0;
            if (Distance <= 3)
            {
                NewAlpha = 1 - (.25 * Distance);
            }
            return NewAlpha;
        }

        private int GetZindex(Double Distance, int i)
        {
            int Zindex = ((int)Distance);
            Zindex = -1 * Zindex;
            return Zindex;
        }




        // --------------------------------------------------------------------------------------
        // UPDATE POSITION OF CAROUSEL FUNCTIONS
        // --------------------------------------------------------------------------------------
        //
        // This section contains functions that update the positions to match new values set by
        // the distribution functions.  Updates are slide (animated) and jump (no animation)

        private void GoToItem(int ID)
        {
            MySlider.Value = ID;
        }


        private void JumpToPosition()
        {
            for (int i = 0; i < CarouselList.Count; i++)
            {
                CarouselItem ThisItem = CarouselList[i];
                Canvas.SetLeft(ThisItem, ThisItem.NewPosition);
                Canvas.SetTop(ThisItem, ThisItem.NewTop);
                Canvas.SetZIndex(ThisItem, ThisItem.NewZindex);

                ThisItem.ItemScale.ScaleX = ThisItem.NewScale;
                ThisItem.ItemScale.ScaleY = ThisItem.NewScale;
                ThisItem.Content.Opacity = ThisItem.NewAlpha; 
            }
        }

        public void Slide()
        {
            Boolean SlideComplete = false;

            // update the values for each item
            for (int i = 0; i < CarouselList.Count; i++)
            {
                GetCurrentValues(i);
                CarouselItem ThisItem = CarouselList[i];

                // Set the Change Values
                Double ChangePosition = ThisItem.NewPosition - ThisItem.Position;
                ChangePosition = ChangePosition / 2;
                ChangePosition = ThisItem.Position + ChangePosition;

                Double ChangeTop = ThisItem.NewTop - ThisItem.Top;
                ChangeTop = ChangeTop / 2;
                ChangeTop = ThisItem.Top + ChangeTop;

                Double ChangeScale = ThisItem.NewScale - ThisItem.Scale;
                ChangeScale = ChangeScale / 2;
                ChangeScale = ThisItem.Scale + ChangeScale;
                if (ChangeScale > 1)
                {
                    ChangeScale = ChangeScale - 1;
                }

                Double ChangeAlpha = ThisItem.NewAlpha - ThisItem.Alpha;
                ChangeAlpha = ChangeAlpha / 2;
                ChangeAlpha = ThisItem.Alpha + ChangeAlpha;

                // Jump to final values if change is very small
                if ( -1 < ChangePosition && ChangePosition < 1 )
                {
                    ChangePosition = ThisItem.NewPosition;
                    ChangeTop = ThisItem.NewTop;
                    ChangeScale = ThisItem.NewScale;
                    ChangeAlpha = ThisItem.NewAlpha;
                    SlideComplete = true;
                }

                // Set the new values
                Canvas.SetLeft(ThisItem, ChangePosition);
                Canvas.SetTop(ThisItem, ChangeTop);
                Canvas.SetZIndex(ThisItem, ThisItem.NewZindex); // This will cause problems

                ThisItem.ItemScale.ScaleX = ChangeScale;
                ThisItem.ItemScale.ScaleY = ChangeScale;
                ThisItem.Content.Opacity = ChangeAlpha;
            }

            // if the slide is complete stop the timer
            if (SlideComplete == true)
            {
                SlideTimer.Stop();
            }
        }

        public void SlideTimer_Tick(object sender, EventArgs e)
        {
            Slide();
        }



        // --------------------------------------------------------------------------------------
        // SLIDER VALUE CHANGED EVENTS
        // --------------------------------------------------------------------------------------
        //
        // This section handles the slider value changed event and updates display

        private void SliderValueChangedEvent(object sender, System.Windows.RoutedPropertyChangedEventArgs<double> e)
		{
            if (CarouselList != null && CarouselList.Count > 0)
            {
                ShowTitle((int)MySlider.Value);
                SlideTimer.Stop();
                MySlider.Value = Math.Round(MySlider.Value);
                DistributeItems();
                Slide();
                SlideTimer.Start();
            }
		}

        private void StepLeft()
        {
            if (CarouselList != null && CarouselList.Count > 0)
            {
                if (MySlider.Value > MySlider.Minimum)
                {
                    MySlider.Value = MySlider.Value - 1;
                }
            }
        }

        private void StepRight()
        {
            if (CarouselList != null && CarouselList.Count > 0)
            {
                if (MySlider.Value < MySlider.Maximum)
                {
                    MySlider.Value = MySlider.Value + 1;
                }
            }
        }





        // --------------------------------------------------------------------------------------
        // MOUSE EVENTS
        // --------------------------------------------------------------------------------------
        //
        // This section contain mouse event handlers

        private void ClickEvent(object sender, System.Windows.RoutedEventArgs e)
        {
            String SenderName = ((Control)sender).Name;

            switch (SenderName)
            {
                case "ScrollLeft":
                    StepLeft();
                    break;

                case "ScrollRight":
                    StepRight();
                    break;
            }
        }

        private void VideoTitle_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            TextBlock vidTitleTextBlock = sender as TextBlock;
            if (vidTitleTextBlock != null && vidTitleTextBlock.Tag is ProductItem)
            {
                string productName = ((ProductItem)vidTitleTextBlock.Tag).Title;
                string currentSiteUrl = Microsoft.SharePoint.Client.ApplicationContext.Current.Url;
                Uri targetUri = new Uri(String.Format("{0}/Pages/Product.aspx?Product={1}", currentSiteUrl, productName));

                HtmlPage.Window.Navigate(targetUri);
            }
        }




// --------------------------------------------------------------
// End Class
	}
}